# dgrmapping.py - A way to create movement for DGRs.
# Copyright 2009 Nick Renny <nickrenny@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

################################################################################
# Imports
################################################################################

# !/usr/bin/env python


import os
import logging
import datetime
import time
import json
from dgrWalking import SavedMapPoint
from dgrWalking import tUser
from django.utils import simplejson
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp import util
from google.appengine.ext import db


SIMPLE_TYPES = (int, long, float, bool, dict, basestring, list)

class MainPage(webapp.RequestHandler):
    """ Renders the main template."""
    def get(self):
        path = os.path.join(os.path.dirname(__file__), "kbMap.html")
        twitteruser = self.request.get('tuser')
        template_values = { 'html_title': twitteruser + ' went walking', }
        self.response.out.write(template.render(path, template_values))

class DroidPage(webapp.RequestHandler):
    """ Renders the droid template."""
    def get(self):
        path = os.path.join(os.path.dirname(__file__), "droidMap.html")
        twitteruser = self.request.get('tuser')
        template_values = { 'html_title': twitteruser + ' went walking', }
        self.response.out.write(template.render(path, template_values))

class RPCHandler(webapp.RequestHandler):
    """ Allows the functions defined in the RPCMethods class to be RPCed."""
    def __init__(self):
        webapp.RequestHandler.__init__(self)
        self.methods = RPCMethods()

    def get(self):
        func = None

        action = self.request.get('action')
        if action:
            if action[0] == '_':
                self.error(403) # access denied
                return
            else:
                func = getattr(self.methods, action, None)

        if not func:
            self.error(404) # file not found
            return

        args = ()
        while True:
            key = 'arg%d' % len(args)
            val = self.request.get(key)
            if val:
                args += (simplejson.loads(val),)
            else:
                break
        result = func(*args)
        self.response.out.write(simplejson.dumps(result))


class RPCMethods:
    """ Defines the methods that can be RPCed.
    NOTE: Do not allow remote callers access to private/protected "_*" methods.
    """
    
    
    def Add(self, *args):
        # The JSON encoding may have encoded integers as strings.
        # Be sure to convert args to any mandatory type(s).
        ints = [int(arg) for arg in args]
        return sum(ints)
    
    def GetWanderings(self, twitteruser):
        
        logging.debug ("wanderings twitter user = " + twitteruser)
        #if twitteruser == '':
        #    wanderings = None
        #else:
        locations = db.GqlQuery('SELECT * FROM SavedMapPoint where user = :1 order by date desc LIMIT 25', twitteruser)
        wanderings = json.encode(locations)
        
        return wanderings

    def GetDroids(self):
        
        logging.debug ("droid map twitter called ")
        #if twitteruser == '':
        #    wanderings = None
        #else:
        locations = db.GqlQuery('SELECT * FROM tUser')
        droids = json.encode(locations)
        
        return droids
        
    def to_dict(self, model):
        output = {}

        for key, prop in model.properties().iteritems():
            value = getattr(model, key)

            if value is None or isinstance(value, SIMPLE_TYPES):
                output[key] = value
            elif isinstance(value, datetime.date):
                # Convert date/datetime to ms-since-epoch ("new Date()").
                ms = time.mktime(value.utctimetuple()) * 1000
                ms += getattr(value, 'microseconds', 0) / 1000
                output[key] = int(ms)
            elif isinstance(value, db.Model):
                output[key] = to_dict(value)
            else:
                raise ValueError('cannot encode ' + repr(prop))

        return output   
            
def main():
    app = webapp.WSGIApplication([
        ('/dgrmaps', MainPage),
        ('/droidmaps', DroidPage),
        ('/rpc', RPCHandler),
        ], debug=False)
    util.run_wsgi_app(app)

if __name__ == '__main__':
    logging.debug ('dgrmapping')
    main()